package view.purchasing;

import com.toedter.calendar.JDateChooser;
import java.awt.Color;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import main.ServicesList;
import model.inventory.Hadiah;
import model.inventory.Item;
import model.inventory.ItemBonus;
import model.inventory.ItemDiskon;
import model.inventory.ItemHpp;
import model.inventory.ItemStok;
import model.publics.Supplier;
import model.purchasing.OrderDetail;
import model.purchasing.OrderMst;
import model.purchasing.TorderDetail;
import model.purchasing.TorderMst;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;
import org.apache.log4j.Logger;
import utility.Constants;
import utility.NameValueList;
import utility.StringUtils;
import utility.com.ComponentUtils;
import utility.com.TableCellListener;
import utility.com.TableUtil;
import utility.com.TextComponentUtils;
import utility.typeSafe.DiskonType;
import utility.typeSafe.HitungBonus;
import utility.typeSafe.JenisBonus;
import utility.typeSafe.SatuanBonus;
import view.TransaksiTemplate;
import view.lookup.LookupScheduleFrm;
import view.lookup.LookupSimpleFrm;

public final class OrderFrm extends TransaksiTemplate {

    private static final DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
    
    private OrderTM orderTM;
    private OrderMst orderMst;

    private TableCellListener tableCellListener;// = new TableCellListener(grid, DetailAction);
    private ItemListener itemListener = new OrdersListener();
    
    private static Logger log = Logger.getLogger(OrderFrm.class);
    private Object oldValue, newValue;
    
    final JTextField itemCEditor = new JTextField();    
    final JTextField ctnCEditor = new JTextField();    
    final JTextField pcsCEditor = new JTextField();    
    
    private static final int COL_NO     = 0;
    private static final int COL_PLU    = 1;
    private static final int COL_NAMA   = 2;
    private static final int COL_STOK   = 3;
    private static final int COL_QCTN   = 4;
    private static final int COL_FRAKSI = 5;
    private static final int COL_QPCS   = 6;
    private static final int COL_HARGA  = 7;
    private static final int COL_DISKON = 8;
    private static final int COL_PPN    = 9;
    private static final int COL_JUMLAH = 10;
    private static final int COL_QBONUS = 11;
    private static final int COL_FBONUS = 12;
    private static final int COL_ITEMBONUS = 13;
                
    public OrderFrm() {
        initComponents();
        initComponentsRules();
    }
    
    private void lookupMaster(int purpose, String param) {
        Object object = new LookupSimpleFrm().execute(purpose, param);
        if (object != null) { setMaster(purpose, object); }
    }
    
    private void getMaster(int purpose, String kode) {
        switch (purpose) {
           case Constants.LOOKUP_ITEM:
                Item item = ServicesList.getItemService().getItem(kode);
                if (item != null) {setMaster(purpose, item); }
                else { lookupMaster(purpose, itemCEditor.getText()); }
                break;
               
           case Constants.LOOKUP_SUPPLIER:
                Supplier suplier = ServicesList.getSupplierService().getSupplier(kode);
                if (suplier != null) {setMaster(purpose, suplier); }
                else { lookupMaster(purpose, txtSupplier.getText()); }
                break;
               
           case Constants.LOOKUP_PO:
                OrderMst order = ServicesList.getOrderService().get(kode);
                if (order != null) {setMaster(purpose, order); }
                else { lookupMaster(purpose, txtRevisi.getText()); }
                break;    
                              
           default: break;    
        }
    }
    
    private void setMaster(int purpose, Object object) {
         if (object != null) {
            switch (purpose) {
                case Constants.LOOKUP_ITEM:
                   
                    boolean isItemInDetails = false;
                    int row = 0;
                    int itemId = ((Item) object).getId();
                    
                    for (OrderDetail detail:orderMst.getOrderDetails()) {
                        if(detail.getItem()!=null && detail.getItem().getId()== itemId) {
                            isItemInDetails=true;
                            break;
                        } row++;
                    }
                    
                    if (isItemInDetails) {
                        JOptionPane.showMessageDialog(this, "Barang sudah ada.", "Informasi",JOptionPane.INFORMATION_MESSAGE);
                        grid.setRowSelectionInterval(row, row);
                        grid.setColumnSelectionInterval(COL_QCTN, COL_QCTN);
                        grid.requestFocus();
                        
                    } else {
                        row = grid.getSelectedRow();
                        orderMst.getOrderDetails().get(row).setItem((Item) object);
                        orderMst.getOrderDetails().get(row).getId().setItemId(itemId);

                        //cari juga hpp
                        ItemHpp hpp = ServicesList.getItemHppService().get(itemId, dtpOrder.getDate()); 
                        if (hpp==null) {
                            JOptionPane.showMessageDialog(this, "Harga belum diseting.", "Error",JOptionPane.ERROR_MESSAGE);
                        } else {
                            orderMst.getOrderDetails().get(row).setItemHpp(hpp);
                            orderMst.getOrderDetails().get(row).setUnit(hpp.getUnit());
                            orderMst.getOrderDetails().get(row).setTop(hpp.getTop());
                            calculateDiskon(row);
                        }

                        ItemStok stok = ServicesList.getItemStokService().get(((Item) object).getId(), Constants.GUDANG_INDUK); 
                        if (stok!=null) {
                            orderMst.getOrderDetails().get(row).setStok(stok.getStok());
                        }

                        orderTM.fireTableRowsUpdated(row, row);
                    }    
                    break;
                    
                case Constants.LOOKUP_SUPPLIER:
                    orderMst.setSupplier((Supplier) object);
                    txtSupplier.setText(
                            orderMst.getSupplier().getKode().concat(" (")
                            .concat(orderMst.getSupplier().getNama())
                            .concat(")"));
                    orderMst.setPkp(((Supplier) object).getSuprincipal().getPkp());
                    orderMst.setLeadTime(((Supplier) object).getSuprincipal().getLeadTime());
                    txtAddTOP.requestFocus();
                    break;
                    
                case Constants.LOOKUP_PO:
                    revisiData((OrderMst) object);
                    break;    
              
                default: break;    
            }
        }
    }
    
    private void calculateDiskon(int row) {
        if (orderMst.getOrderDetails().get(row).getItemHpp()!=null) {
            Date now = StringUtils.truncDate(dtpOrder.getDate());
            ItemHpp itemHpp = orderMst.getOrderDetails().get(row).getItemHpp();
            BigDecimal diskon = BigDecimal.ZERO;       
            BigDecimal harga = itemHpp.getPrice();
            String discDesc = "DISC ";

            //hitung diskon
            for (ItemDiskon disk: itemHpp.getItemDiskons()) {
                Date beginDate = StringUtils.truncDate(disk.getBeginDate());
                Date endDate = StringUtils.truncDate(disk.getEndDate());
                if((beginDate.compareTo(now)<=0) && (endDate.compareTo(now)>=0)) {
                    String jenis = DiskonType.PERSENTASE.toString(); 
                    if (disk.getJenis().equals(DiskonType.PERSENTASE.toString())) {
                        BigDecimal tmpHarga = harga.subtract(diskon);
                        BigDecimal tmpDiskon = disk.getDiskon().divide(Constants.PERSENT_DIVIDER, 3, RoundingMode.HALF_UP);
                        diskon = diskon.add(tmpHarga.multiply(tmpDiskon));
                        discDesc=discDesc.concat(StringUtils.formatNumber(disk.getDiskon())).concat("%, ");
                    } else { 
                        diskon = diskon.add(disk.getDiskon()); 
                        discDesc=discDesc.concat("Rp ").concat(StringUtils.formatNumber(disk.getDiskon())).concat(", ");
                    }
                }
            }

            //update item hppp biar mudah dalam perhitungan
            BigDecimal hpp = harga.subtract(diskon);
            BigDecimal ppn = BigDecimal.ZERO;
            if (itemHpp.getPkp()) {
                ppn = hpp.multiply(Constants.TAX_MULTIPLYER);
            }

            itemHpp.setDiskon(diskon);
            itemHpp.setHpp(hpp);
            itemHpp.setPpn(ppn);
            itemHpp.setHppAfterPpn(hpp.add(ppn));

            //catat keterangan diskon, fraksi, dan harga in crt
            orderMst.getOrderDetails().get(row).setDiskonDesc(discDesc);
            orderMst.getOrderDetails().get(row).setFraksi(itemHpp.getFraksi());
            orderMst.getOrderDetails().get(row).setPrice(itemHpp.getPrice());
        }
    }
    
    private void calculateBonus(int row) {
        if (orderMst.getOrderDetails().get(row).getItemHpp() != null || 
                orderMst.getOrderDetails().get(row).getItemHpp().getItemBonuses() != null) {
            
            Date now = StringUtils.truncDate(dtpOrder.getDate());
            ItemHpp itemHpp = orderMst.getOrderDetails().get(row).getItemHpp();

            BigDecimal qtotal = orderMst.getOrderDetails().get(row).getQtyCrt()
                    .multiply(BigDecimal.valueOf(orderMst.getOrderDetails().get(row).getFraksi()))
                    .add(orderMst.getOrderDetails().get(row).getQtyPcs());

            BigDecimal qcrt = qtotal.divide(BigDecimal.valueOf(orderMst.getOrderDetails().get(row).getFraksi()), RoundingMode.DOWN); 
            int jumlahBonus = 0;
            int fraksiBonus = 0;

            BigDecimal harga = itemHpp.getPrice();
            String bonusDesc = "";
            String bonusJenis = "";
            Hadiah hadiah = null;

            //cari bonus
            //cuma 1 bonus aja
            boolean found=false; 
            for (ItemBonus bonus: itemHpp.getItemBonuses()) {
                Date beginDate = StringUtils.truncDate(bonus.getBeginDate());
                Date endDate = StringUtils.truncDate(bonus.getEndDate());

                if((beginDate.compareTo(now)<=0) && (endDate.compareTo(now)>=0) && !found) {

                    String satBonus = SatuanBonus.IN_CTN.toString();
                    if (bonus.getBatas() <= qcrt.intValue()) {
                        bonusJenis = bonus.getJenisBonus(); 

                        //jumlah bonusnya berapa
                        if (bonus.getCaraHitung().equals(HitungBonus.MULTIPLY.toString())) {
                            jumlahBonus = (qcrt.intValue() / bonus.getBatas()) * bonus.getBonus();
                            bonusDesc="BONUS "+bonusJenis+" "+bonus.getBatas()+"x"+bonus.getBonus();
                        }else { 
                            jumlahBonus = bonus.getBonus();
                            bonusDesc="BONUS "+bonusJenis+" "+bonus.getBatas()+"+"+bonus.getBonus();
                        }    

                        //fraksinya berapa apa
                        if (satBonus.equals(SatuanBonus.IN_CTN.toString())) { 
                            fraksiBonus=itemHpp.getFraksi(); }
                        else { fraksiBonus= 1;}

                        //hadiahnya apa
                        if(bonusJenis.equals(JenisBonus.TT.toString())) {
                            hadiah = bonus.getHadiah();
                        }
                    }
                }
                found=true;
            }

            //catat keterangan bonus, fraksi, dan harga in crt
            orderMst.getOrderDetails().get(row).setHadiah(hadiah);
            orderMst.getOrderDetails().get(row).setBonusDesc(bonusDesc);
            orderMst.getOrderDetails().get(row).setFraksiBonus(fraksiBonus);
            orderMst.getOrderDetails().get(row).setJenisBonus(bonusJenis);
            orderMst.getOrderDetails().get(row).setQtyBonus(BigDecimal.valueOf(jumlahBonus));
        }
    }
     
    private void calculate(int row) {
        if (orderMst.getOrderDetails().get(row).getItemHpp() != null) {
            OrderDetail orderDetail = orderMst.getOrderDetails().get(row);
            BigDecimal hargaInPcs = orderDetail.getPrice().divide(BigDecimal.valueOf(orderDetail.getFraksi()), 2, RoundingMode.HALF_UP);
            BigDecimal diskonInPcs = orderDetail.getItemHpp().getDiskon().divide(BigDecimal.valueOf(orderDetail.getFraksi()), 3, RoundingMode.HALF_UP);
            BigDecimal qtotal = orderDetail.getQtyCrt()
                    .multiply(BigDecimal.valueOf(orderDetail.getFraksi()))
                    .add(orderDetail.getQtyPcs());

            BigDecimal diskon, amount, ppn, total;
            diskon = diskonInPcs.multiply(qtotal);
            amount = hargaInPcs.multiply(qtotal).subtract(diskon);

            if (BigDecimal.ZERO.equals(orderDetail.getItemHpp().getPpn())) { ppn = BigDecimal.ZERO;} 
            else {ppn = amount.multiply(Constants.TAX_MULTIPLYER);}
            total = amount.add(ppn);

            orderMst.getOrderDetails().get(row).setAmount(total);
            orderMst.getOrderDetails().get(row).setDiskon(diskon);
            orderMst.getOrderDetails().get(row).setPpn(ppn);

            //calculateDiskon(row);
            calculateBonus(row);
            orderTM.fireTableRowsUpdated(row, row);

            BigDecimal _subtotal = BigDecimal.ZERO;
            BigDecimal _diskon = BigDecimal.ZERO;
            BigDecimal _ppn = BigDecimal.ZERO;
            BigDecimal _total = BigDecimal.ZERO;
            for (OrderDetail detail: orderMst.getOrderDetails()) {
                _subtotal = _subtotal.add(detail.getAmount().subtract(detail.getDiskon()).add(detail.getPpn()));
                _diskon = _diskon.add(detail.getDiskon());
                _ppn = _ppn.add(detail.getPpn());
                _total = _total.add(detail.getAmount());
            }

            txtSubtotal.setText(StringUtils.formatNumber(_subtotal));
            txtDiskon.setText(StringUtils.formatNumber(_diskon));
            txtTax.setText(StringUtils.formatNumber(_ppn));
            txtTotal.setText(StringUtils.formatNumber(_total));
        }        
    }
    
    private void moveNext() {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.focusNextComponent();
    }
    
    class ActionKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {} 
        @Override public void keyReleased(KeyEvent e) {}
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_F2: 
                    switch(e.getComponent().getName()) {
                        case "txtSupplier": 
                            lookupMaster(Constants.LOOKUP_SUPPLIER, txtSupplier.getText()); 
                            break;
                        case "itemCEditor": 
                            lookupMaster(Constants.LOOKUP_ITEM, itemCEditor.getText()); 
                            break; 
                        case "txtRevisi": 
                            lookupMaster(Constants.LOOKUP_PO, txtRevisi.getText()); 
                            break;    
                    };
                break;  
                
                case KeyEvent.VK_ENTER: 
                    switch(e.getComponent().getName()) {
                        case "itemCEditor": 
                            newValue = itemCEditor.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_ITEM, itemCEditor.getText()); }
                            break;
                            
                        case "txtSupplier": 
                            newValue = txtSupplier.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_SUPPLIER, txtSupplier.getText()); }
                            else {moveNext();}
                            break;
                            
                         case "txtRevisi": 
                            newValue = txtRevisi.getText();
                            if (!newValue.equals(oldValue)) { getMaster(Constants.LOOKUP_PO, txtRevisi.getText()); }
                            else {moveNext();}
                            break;
                             
                       default: moveNext(); break;
                    };
                break;      
            }
        }
    }
    
    class ActionFocusGained implements FocusListener {
        @Override public void focusGained(FocusEvent e) { 
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { oldValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { oldValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { oldValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { oldValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { oldValue = ((JDateChooser) componen).getDate(); }
        }
        
        @Override public void focusLost(FocusEvent e) {
            Component componen = (Component) e.getSource(); 
            if (componen instanceof JTextField) { newValue = ((JTextField) componen).getText();
            }else if (componen instanceof JComboBox) { newValue = ((JComboBox) componen).getSelectedIndex();
            }else if (componen instanceof JCheckBox) { newValue = ((JCheckBox) componen).isSelected();
            }else if (componen instanceof JTextArea) { newValue = ((JTextArea) componen).getText(); 
            }else if (componen instanceof JDateChooser) { newValue = ((JDateChooser) componen).getDate(); }
            
            if (!newValue.equals(oldValue)) { initButtonState(true); }
        }
    }

    class GridKeyListener implements KeyListener {
        @Override public void keyTyped(KeyEvent e) {};
        @Override public void keyReleased(KeyEvent e) {};
        
        @Override public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) { 
                case KeyEvent.VK_ENTER:
                    if ((grid.getSelectedRow() == grid.getRowCount()-1) 
                            && grid.getSelectedColumn() == COL_QPCS) {
                        orderMst.getOrderDetails().add(new OrderDetail());
                        orderTM.fireTableDataChanged(); 
                    }
                    break;
            }        
        };
    }
    
    Action DetailAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            TableCellListener tblCellListener = (TableCellListener)e.getSource();
            int row = tblCellListener.getRow();
            int col = tblCellListener.getColumn();
                
            Object oldVal = tblCellListener.getOldValue();
            Object newVal = tblCellListener.getNewValue();
            
            if(oldVal==null) {oldVal="";}
            if(newVal==null) {newVal="";}
                
            if (!oldVal.equals(newValue)) {
                switch (col) {
                    case COL_QCTN: 
                        BigDecimal qcrt = TextComponentUtils.parseNumberToBigDecimal((String)newVal);
                        orderMst.getOrderDetails().get(row).setQtyCrt(qcrt);
                        calculate(row);
                        initButtonState(true);
                        break;
                    case COL_QPCS: 
                        BigDecimal qpcs = TextComponentUtils.parseNumberToBigDecimal((String)newVal);
                        orderMst.getOrderDetails().get(row).setQtyPcs(qpcs);
                        calculate(row);
                        initButtonState(true);
                        break;
                }
            }
        }
    };     
    
    class OrdersListener implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            if(e.getStateChange()==ItemEvent.SELECTED) {
                int id = Integer.parseInt(((NameValueList) e.getItem()).getKey());
                loadData(id);
            }
        }
    }
    
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        dtpOrder = new com.toedter.calendar.JDateChooser();
        txtRevisi = new javax.swing.JTextField();
        txtSupplier = new javax.swing.JTextField();
        txtAddTOP = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        chkTahan = new javax.swing.JCheckBox();
        cmbOrders = new javax.swing.JComboBox();
        jLabel5 = new javax.swing.JLabel();
        txtNomor = new javax.swing.JTextField();
        jLabel6 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        grid = new javax.swing.JTable();
        jToolBar1 = new javax.swing.JToolBar();
        btnAuto = new javax.swing.JButton();
        btnNew = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        btnDelete = new javax.swing.JButton();
        btnPosting = new javax.swing.JButton();
        btnRevisi = new javax.swing.JButton();
        btnClose = new javax.swing.JButton();
        btnPrint = new javax.swing.JButton();
        txtNotes = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        txtTax = new javax.swing.JTextField();
        txtTotal = new javax.swing.JTextField();
        txtDiskon = new javax.swing.JTextField();
        txtSubtotal = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        txtLeadTime = new javax.swing.JTextField();
        jLabel12 = new javax.swing.JLabel();
        txtDivisi = new javax.swing.JTextField();
        txtTOP = new javax.swing.JTextField();
        jLabel13 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        dtpOrder.setName("dtpOrder"); // NOI18N

        txtRevisi.setName("txtRevisi"); // NOI18N

        txtSupplier.setName("txtSupplier"); // NOI18N

        txtAddTOP.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtAddTOP.setName("txtAddTOP"); // NOI18N

        jLabel1.setText("Tgl PO :");

        jLabel2.setText("Supplier :");

        jLabel3.setText("Revisi PO :");

        jLabel4.setText("Add TOP :");

        chkTahan.setText("Tahan PO");
        chkTahan.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        chkTahan.setName("chkTahan"); // NOI18N

        cmbOrders.setName("cmbOrders"); // NOI18N

        jLabel5.setText("Divisi PO :");

        txtNomor.setEnabled(false);
        txtNomor.setFocusable(false);
        txtNomor.setName("txtNomor"); // NOI18N

        jLabel6.setText("Nomor PO :");

        grid.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        grid.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        grid.setRowHeight(20);
        grid.setRowMargin(5);
        jScrollPane1.setViewportView(grid);

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);
        jToolBar1.setMaximumSize(new java.awt.Dimension(32767, 20));
        jToolBar1.setSize(this.getWidth(), 50);

        btnAuto.setIcon(new javax.swing.ImageIcon(getClass().getResource("/reload.png"))); // NOI18N
        btnAuto.setText("Auto Order");
        btnAuto.setFocusable(false);
        btnAuto.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnAuto.setName("btnAuto"); // NOI18N
        btnAuto.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnAuto.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAutoActionPerformed(evt);
            }
        });
        jToolBar1.add(btnAuto);

        btnNew.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_add.png"))); // NOI18N
        btnNew.setText("Tambah");
        btnNew.setFocusable(false);
        btnNew.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnNew.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnNew.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNewActionPerformed(evt);
            }
        });
        jToolBar1.add(btnNew);

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/filesave.png"))); // NOI18N
        btnSave.setText("Save");
        btnSave.setFocusable(false);
        btnSave.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveActionPerformed(evt);
            }
        });
        jToolBar1.add(btnSave);

        btnDelete.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit_remove.png"))); // NOI18N
        btnDelete.setText("Delete Row");
        btnDelete.setFocusable(false);
        btnDelete.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnDelete.setName("btnDelete"); // NOI18N
        btnDelete.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDeleteActionPerformed(evt);
            }
        });
        jToolBar1.add(btnDelete);

        btnPosting.setIcon(new javax.swing.ImageIcon(getClass().getResource("/edit.png"))); // NOI18N
        btnPosting.setText("Posting");
        btnPosting.setFocusable(false);
        btnPosting.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnPosting.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPosting.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnPostingActionPerformed(evt);
            }
        });
        jToolBar1.add(btnPosting);

        btnRevisi.setIcon(new javax.swing.ImageIcon(getClass().getResource("/search.png"))); // NOI18N
        btnRevisi.setText("Revisi");
        btnRevisi.setFocusable(false);
        btnRevisi.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnRevisi.setName("btnRevisi"); // NOI18N
        btnRevisi.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnRevisi.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRevisiActionPerformed(evt);
            }
        });
        jToolBar1.add(btnRevisi);
        btnRevisi.getAccessibleContext().setAccessibleDescription("");

        btnClose.setIcon(new javax.swing.ImageIcon(getClass().getResource("/help.png"))); // NOI18N
        btnClose.setText("Close");
        btnClose.setFocusable(false);
        btnClose.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnClose.setName("btnClose"); // NOI18N
        btnClose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCloseActionPerformed(evt);
            }
        });
        jToolBar1.add(btnClose);

        btnPrint.setIcon(new javax.swing.ImageIcon(getClass().getResource("/print.png"))); // NOI18N
        btnPrint.setText("Print");
        btnPrint.setFocusable(false);
        btnPrint.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        btnPrint.setName(""); // NOI18N
        btnPrint.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPrint.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnPrintActionPerformed(evt);
            }
        });
        jToolBar1.add(btnPrint);

        txtNotes.setName("txtNotes"); // NOI18N

        jLabel7.setText("Keterangan :");

        txtTax.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtTax.setEnabled(false);
        txtTax.setFocusable(false);
        txtTax.setName("txtTax"); // NOI18N

        txtTotal.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtTotal.setEnabled(false);
        txtTotal.setFocusable(false);
        txtTotal.setName("txtTotal"); // NOI18N

        txtDiskon.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtDiskon.setEnabled(false);
        txtDiskon.setFocusable(false);
        txtDiskon.setName("txtDiskon"); // NOI18N

        txtSubtotal.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtSubtotal.setEnabled(false);
        txtSubtotal.setFocusable(false);
        txtSubtotal.setName("txtSubtotal"); // NOI18N

        jLabel8.setText("Subtotal :");

        jLabel9.setText("Diskons :");

        jLabel10.setText("PPN :");

        jLabel11.setText("Total :");

        txtLeadTime.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtLeadTime.setEnabled(false);
        txtLeadTime.setFocusable(false);
        txtLeadTime.setName("txtLeadTime"); // NOI18N

        jLabel12.setText("Lead TIme :");

        txtDivisi.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtDivisi.setEnabled(false);
        txtDivisi.setFocusable(false);
        txtDivisi.setName("txtDivisi"); // NOI18N

        txtTOP.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        txtTOP.setEnabled(false);
        txtTOP.setFocusable(false);
        txtTOP.setName("txtTOP"); // NOI18N

        jLabel13.setText("TOP :");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING))
                .addGap(5, 5, 5)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(txtAddTOP, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel13)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(txtTOP, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(12, 12, 12)
                        .addComponent(jLabel12)
                        .addGap(2, 2, 2)
                        .addComponent(txtLeadTime, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(txtDivisi, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(chkTahan))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(txtRevisi, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(dtpOrder, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel6)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(cmbOrders, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtNomor, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(txtSupplier)
                    .addComponent(txtNotes))
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(337, 337, 337)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel8)
                            .addComponent(jLabel9))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(txtDiskon, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtSubtotal, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel11)
                            .addComponent(jLabel10))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(txtTotal, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(txtTax, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addGap(10, 10, 10))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(dtpOrder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(txtNomor, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel6)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtRevisi, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(cmbOrders, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel3))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtSupplier, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel2))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(txtLeadTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel12)
                                .addComponent(txtDivisi, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel5)
                                .addComponent(chkTahan))
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(txtAddTOP, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel4)
                                .addComponent(jLabel13)
                                .addComponent(txtTOP, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtNotes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel7))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtTax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel10))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(txtTotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel11)
                            .addComponent(txtDiskon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel9)))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(txtSubtotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jLabel8)))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewActionPerformed
        initForm();
        cmbOrders.setModel(new DefaultComboBoxModel());
        txtSupplier.requestFocus();
    }//GEN-LAST:event_btnNewActionPerformed

    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed
        validasi();
    }//GEN-LAST:event_btnSaveActionPerformed

    private void btnPrintActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPrintActionPerformed
        printOrder();
    }//GEN-LAST:event_btnPrintActionPerformed

    private void btnPostingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPostingActionPerformed
        posting();
    }//GEN-LAST:event_btnPostingActionPerformed

    private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
        closing();
    }//GEN-LAST:event_btnCloseActionPerformed

    private void btnRevisiActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRevisiActionPerformed
        OrderMst order = ServicesList.getOrderService().get(orderMst.getId());
        revisiData(order);
    }//GEN-LAST:event_btnRevisiActionPerformed

    private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed
        deleteRow();
    }//GEN-LAST:event_btnDeleteActionPerformed

    private void btnAutoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAutoActionPerformed
        createAutoOrder();
    }//GEN-LAST:event_btnAutoActionPerformed

    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAuto;
    private javax.swing.JButton btnClose;
    private javax.swing.JButton btnDelete;
    private javax.swing.JButton btnNew;
    private javax.swing.JButton btnPosting;
    private javax.swing.JButton btnPrint;
    private javax.swing.JButton btnRevisi;
    private javax.swing.JButton btnSave;
    private javax.swing.JCheckBox chkTahan;
    private javax.swing.JComboBox cmbOrders;
    private com.toedter.calendar.JDateChooser dtpOrder;
    private javax.swing.JTable grid;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JTextField txtAddTOP;
    private javax.swing.JTextField txtDiskon;
    private javax.swing.JTextField txtDivisi;
    private javax.swing.JTextField txtLeadTime;
    private javax.swing.JTextField txtNomor;
    private javax.swing.JTextField txtNotes;
    private javax.swing.JTextField txtRevisi;
    private javax.swing.JTextField txtSubtotal;
    private javax.swing.JTextField txtSupplier;
    private javax.swing.JTextField txtTOP;
    private javax.swing.JTextField txtTax;
    private javax.swing.JTextField txtTotal;
    // End of variables declaration//GEN-END:variables

    @Override
    public void setVisible(boolean value) {
        super.setVisible(value);
        txtSupplier.requestFocusInWindow();
    }
     
    @Override
    public void execute(boolean withVisible, int id) {
    }

     public void execute2(boolean withVisible, long id) {
        setLocationRelativeTo(null);
        
        if(id>0) {
            loadData(id);
            showOrderList(orderMst.getAutoId());
        }else { initForm(); }
        
        if (withVisible) { setVisible(true); }
    }
     
    @Override
    protected void initForm() {
        if (orderMst!=null) {orderMst=null;}
        orderMst = new OrderMst();
        txtAddTOP.setText("0");
        txtTOP.setText("0");
        txtLeadTime.setText("0");
        txtDivisi.setText("0");
        txtDiskon.setText("0");
        txtNomor.setText("");
        txtRevisi.setText("");
        txtSubtotal.setText("0");
        txtSupplier.setText("");
        txtNotes.setText("004194 010723");
        txtTax.setText("0");
        txtTotal.setText("0");
        dtpOrder.setDate(new Date());
        chkTahan.setSelected(false);
        initGrid(orderMst.getOrderDetails());
        initInputState();
    }

    @Override
    protected void initGrid() {}
    
    protected void initGrid(List<OrderDetail> data) {
        if(orderTM!=null) {orderTM=null;}
        
        grid.removePropertyChangeListener(tableCellListener);
        boolean readOnly = false;
        if (orderMst.getStatusId()!=null) {
            readOnly = orderMst.getStatusId() > 0 ? true:false;
        }
        
        orderTM = new OrderTM(data, readOnly);
        grid.setModel(orderTM);
        
        //hanya yg open aja yg bisa edit detail
        if (orderMst.getStatusId()==null || orderMst.getStatusId() == Constants.STATUS_TRANS_OPEN) {
            int idx=0;
            for (OrderDetail detail : data) {
                if (detail.getItem()!=null) {
                    ItemHpp hpp = ServicesList.getItemHppService().get(detail.getItem().getId(), orderMst.getTransDate());
                    detail.setItemHpp(hpp);
                    calculateDiskon(idx);
                    idx++;
                }
            }
            tableCellListener = new TableCellListener(grid, DetailAction);
        }
                
        DefaultTableCellRenderer rightCellRender = new DefaultTableCellRenderer();
        rightCellRender.setHorizontalAlignment(SwingConstants.RIGHT);
             
        //set alignment
        grid.getColumnModel().getColumn(COL_NO).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_DISKON).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_HARGA).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_FRAKSI).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_JUMLAH).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_PPN).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_QCTN).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_QPCS).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_STOK).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_QBONUS).setCellRenderer(rightCellRender);
        grid.getColumnModel().getColumn(COL_FBONUS).setCellRenderer(rightCellRender);
            
        //cell ony accept number    
        TextComponentUtils.setNumericTextOnly(ctnCEditor);
        TextComponentUtils.setNumericTextOnly(pcsCEditor);
        grid.getColumnModel().getColumn(COL_PLU).setCellEditor(new DefaultCellEditor (itemCEditor));
        grid.getColumnModel().getColumn(COL_QCTN).setCellEditor(new DefaultCellEditor (ctnCEditor));
        grid.getColumnModel().getColumn(COL_QPCS).setCellEditor(new DefaultCellEditor (pcsCEditor));
        
        grid.getColumnModel().getColumn(COL_NO).setPreferredWidth(3);
        grid.getColumnModel().getColumn(COL_PLU).setPreferredWidth(25);
        //grid.getColumnModel().getColumn(COL_NAMA).setPreferredWidth(25);
        grid.getColumnModel().getColumn(COL_STOK).setPreferredWidth(20);
        grid.getColumnModel().getColumn(COL_QCTN).setPreferredWidth(15);
        grid.getColumnModel().getColumn(COL_FRAKSI).setPreferredWidth(10);
        grid.getColumnModel().getColumn(COL_QPCS).setPreferredWidth(10);
        grid.getColumnModel().getColumn(COL_HARGA).setPreferredWidth(30);
        grid.getColumnModel().getColumn(COL_DISKON).setPreferredWidth(40);
        grid.getColumnModel().getColumn(COL_PPN).setPreferredWidth(45);
        grid.getColumnModel().getColumn(COL_JUMLAH).setPreferredWidth(90);
        grid.getColumnModel().getColumn(COL_QBONUS).setPreferredWidth(25);
        grid.getColumnModel().getColumn(COL_FBONUS).setPreferredWidth(25);
        grid.getColumnModel().getColumn(COL_ITEMBONUS).setPreferredWidth(25);
        
        //look style
        final TableCellRenderer header = grid.getTableHeader().getDefaultRenderer();
        grid.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                JLabel lbl = (JLabel) header.getTableCellRendererComponent(table, 
                      value, isSelected, hasFocus, row, column);
                lbl.setBorder(BorderFactory.createEmptyBorder(5,1,5,1));   

                switch (column) {
                    case COL_PLU: lbl.setHorizontalAlignment(SwingConstants.LEFT); break;
                    case COL_NAMA: lbl.setHorizontalAlignment(SwingConstants.LEFT); break; 
                    case COL_ITEMBONUS: lbl.setHorizontalAlignment(SwingConstants.LEFT); break;
                    default: lbl.setHorizontalAlignment(SwingConstants.RIGHT); break;   
                }
                lbl.setForeground(Color.WHITE);
                lbl.setBackground(Color.DARK_GRAY);
                return lbl;
            }
        });
        grid.setGridColor(Color.LIGHT_GRAY);
    }
    
    protected void modelToForm(OrderMst data) {
        txtNomor.setText(data.getTransNum());
        dtpOrder.setDate(data.getTransDate());
        if (data.getRevisedId() != null) {
            String transNum = ServicesList.getOrderService().getTransNum(data.getRevisedId());
            txtRevisi.setText(transNum);
        }
        
        txtSupplier.setText(data.getSupplier().getNama());
        txtAddTOP.setText(data.getAddTop().toString());
        txtTOP.setText(data.getTop().toString());
        txtLeadTime.setText(data.getLeadTime().toString());
        chkTahan.setSelected(data.getHolding());
        txtNotes.setText(data.getNotes());
        txtSubtotal.setText(StringUtils.formatNumber(data.getSubtotal()));
        txtDiskon.setText(StringUtils.formatNumber(data.getDiskon()));
        txtTax.setText(StringUtils.formatNumber(data.getPpn()));
        txtTotal.setText(StringUtils.formatNumber(data.getTotal()));
        initGrid(data.getOrderDetails());
        initInputState();
    }

    @Override
    protected void loadData() {throw new UnsupportedOperationException("Not supported yet.");}
    
    protected void loadData(long id) {
       initForm();
       orderMst = ServicesList.getOrderService().get(id);
       if (orderMst!=null) {modelToForm(orderMst); }
    }
    
    protected TorderMst manageOrder() {
        TorderMst tmpOrder = new TorderMst();
        List<TorderDetail> tmpOrderDetail = new ArrayList<>();
        tmpOrder.setAddTop(Integer.parseInt(txtAddTOP.getText()));
        tmpOrder.setNotes(txtNotes.getText());
        tmpOrder.setTransDate(dtpOrder.getDate());
        tmpOrder.setUserId(ServicesList.getSystemUserService().getActiveUser().getUserName());
                
        for (OrderDetail detail : orderMst.getOrderDetails()) {
            if (detail.getItem()!=null) {
                TorderDetail torderDetail = new TorderDetail();

                Supplier supplier = ServicesList.getSupplierService().getSupplier(detail.getItemHpp().getId().getSupplierId());
                
                torderDetail.setAmount(detail.getAmount());
                torderDetail.setBonusDesc(detail.getBonusDesc());
                torderDetail.setDiskon(detail.getDiskon());
                torderDetail.setDiskonDesc(detail.getDiskonDesc());
                
                torderDetail.setDivOrder(
                    detail.getItem().getDivOrder()==null ? "" : detail.getItem().getDivOrder());
                torderDetail.setFraksi(detail.getFraksi());
                torderDetail.setFraksiBonus(detail.getFraksiBonus());
                
                if (detail.getHadiah() != null) { torderDetail.setHadiahId(detail.getHadiah().getId()); }
                
                torderDetail.getId().setItemId(detail.getItem().getId());
                torderDetail.setJenisBonus(detail.getJenisBonus());
                torderDetail.setPkp(detail.getItemHpp().getPkp());
                torderDetail.setPpn(detail.getPpn());
                torderDetail.setPrice(detail.getPrice());
                torderDetail.setQtyBonus(detail.getQtyBonus());
                torderDetail.setQtyCrt(detail.getQtyCrt());
                torderDetail.setQtyPcs(detail.getQtyPcs());
                torderDetail.setSupplierId(supplier.getId());
                torderDetail.setTop(detail.getTop());
                torderDetail.setUnitId(detail.getUnit().getId());
                torderDetail.setLeadTime(supplier.getSuprincipal().getLeadTime());
                torderDetail.setTorderMst(tmpOrder);
                tmpOrderDetail.add(torderDetail);
            }
        }
        tmpOrder.setTorderDetails(tmpOrderDetail);
        return tmpOrder;
    }
    
    private void syncronizeDetail(){
        List<Integer> emptyItem = new ArrayList<>();
        
        for (int i=0; i<orderMst.getOrderDetails().size(); i++) {
            BigDecimal qcrt = orderMst.getOrderDetails().get(i).getQtyCrt();
            BigDecimal qpcs = orderMst.getOrderDetails().get(i).getQtyPcs();
            
            if ((orderMst.getOrderDetails().get(i).getItem()==null) ||
                    (qcrt.compareTo(BigDecimal.ZERO)==0 && qpcs.compareTo(BigDecimal.ZERO)==0) ) 
            {
                emptyItem.add(i);
            }
        }
        
        for (Integer i: emptyItem) {
            int idx = i;
            orderMst.getOrderDetails().remove(idx);
        }
    }
    
    private void deleteRow () {
        int rowCount = grid.getRowCount();
        int row = grid.getSelectedRow();
        
        if (rowCount==1) {
            OrderDetail emptyData = new OrderDetail();
            orderMst.getOrderDetails().set(row, emptyData);
            orderTM.fireTableRowsUpdated(row, row);
        } else {
            orderMst.getOrderDetails().remove(row);
            orderTM.fireTableRowsDeleted(row, row);
        }
        initInputState();
        initButtonState(true);
    }
    
    @Override
    protected void saveData() {
        long id;
        try{
            if (orderMst.getId() != null || orderMst.getRevisedId() != null) {
                if(orderMst.getId() == null) {
                    String transNum = ServicesList.getSystemNumberingService().getNextNumberDb(Constants.TRANS_PURCHASE_ORDER, dtpOrder.getDate());
                    orderMst.setTransNum(transNum);
                    orderMst.setUserId(ServicesList.getSystemUserService().getActiveUser().getUserName());
                
                } else {
                    orderMst.setUpdatedLog(ServicesList.getSystemUserService().getUserIdLog());
                }
                
                orderMst.setAddTop(Integer.parseInt(txtAddTOP.getText()));
                orderMst.setNotes(txtNotes.getText());
                orderMst.setTransDate(dtpOrder.getDate());
                orderMst.setDivisi(txtDivisi.getText());
                orderMst.setHolding(chkTahan.isSelected());
                orderMst.setLeadTime(Integer.parseInt(txtLeadTime.getText()));
                orderMst.setSubtotal(TextComponentUtils.parseNumberToBigDecimal((String)txtSubtotal.getText()));
                orderMst.setDiskon(TextComponentUtils.parseNumberToBigDecimal((String)txtDiskon.getText()));
                orderMst.setPpn(TextComponentUtils.parseNumberToBigDecimal((String)txtTax.getText()));
                orderMst.setTotal(TextComponentUtils.parseNumberToBigDecimal((String)txtTotal.getText()));
                
                syncronizeDetail();
                ServicesList.getOrderService().save(orderMst);
            
            }else {
                TorderMst torderMst = manageOrder();
                id = ServicesList.getTorderService().save(torderMst);
                if (id>0) {
                    boolean saved = ServicesList.getTorderService().manageOrder(id);
                    if (saved) { 
                        loadData(torderMst.getId()); 
                        showOrderList(id);                   
                        ServicesList.getTorderService().delete(torderMst);
                    }
                }
            }
        } catch(Exception ex){
            log.error(ex);
            JOptionPane.showMessageDialog(this, "Data gagal disimpan."
            ,"Error",JOptionPane.ERROR_MESSAGE);
        }
        initInputState();
    }

    @Override
    protected void validasi() {
        saveData();
    }

    @Override
    protected void posting() {
        boolean saved = false;
        try{
            orderMst.setStatusId(Constants.STATUS_TRANS_POSTED);
            orderMst.setUpdatedLog(ServicesList.getSystemUserService().getUserIdLog());
            saved = ServicesList.getOrderService().save(orderMst);
        } catch(Exception ex){
            log.error(ex);
            JOptionPane.showMessageDialog(this, "Data gagal Posting.", "Error",JOptionPane.ERROR_MESSAGE);
        }
        
         if (saved) { initInputState(); }
    }
    
    protected void revisiData(OrderMst data) {
        if (data!=null) {
            initForm();

            txtSupplier.setText(data.getSupplier().getNama());
            txtAddTOP.setText(data.getAddTop().toString());
            txtTOP.setText(data.getTop().toString());
            txtLeadTime.setText(data.getLeadTime().toString());
            chkTahan.setSelected(data.getHolding());
            txtNotes.setText(data.getNotes());
            txtDivisi.setText(data.getDivisi());
            txtRevisi.setText(data.getTransNum());
            txtSubtotal.setText(StringUtils.formatNumber(data.getSubtotal()));
            txtDiskon.setText(StringUtils.formatNumber(data.getDiskon()));
            txtTax.setText(StringUtils.formatNumber(data.getPpn()));
            txtTotal.setText(StringUtils.formatNumber(data.getTotal()));

            orderMst.setPkp(data.getPkp());
            orderMst.setRevisedId(data.getId());
            orderMst.setSupplier(data.getSupplier());

            orderMst.setOrderDetails(null);
            int idx =0;
            List<OrderDetail> newDetails = new ArrayList<>();
            for (OrderDetail detail : data.getOrderDetails()) {
                if (detail.getItem()!=null) {
                    OrderDetail newDetail = new OrderDetail();
                    newDetail.setAmount(detail.getAmount());
                    newDetail.setBonusDesc(detail.getBonusDesc());
                    newDetail.setDiskon(detail.getDiskon());
                    newDetail.setDiskonDesc(detail.getDiskonDesc());
                    newDetail.setFraksi(detail.getFraksi());
                    newDetail.setFraksiBonus(detail.getFraksiBonus());
                    newDetail.setHadiah(detail.getHadiah()!= null ? detail.getHadiah() : null);
                    newDetail.setItem(detail.getItem());
                    newDetail.setJenisBonus(detail.getJenisBonus());
                    newDetail.setPpn(detail.getPpn());
                    newDetail.setPrice(detail.getPrice());
                    newDetail.setQtyBonus(detail.getQtyBonus());
                    newDetail.setQtyCrt(detail.getQtyCrt());
                    newDetail.setQtyPcs(detail.getQtyPcs());
                    newDetail.setTop(detail.getTop());
                    newDetail.setUnit(detail.getUnit());
                    ItemHpp hpp = ServicesList.getItemHppService().get(detail.getItem().getId(), dtpOrder.getDate()); 
                    newDetail.setItemHpp(hpp);
                    newDetail.setOrderMst(orderMst);
                    newDetails.add(newDetail);
               }
            }
            orderMst.setOrderDetails(newDetails);
            initGrid(newDetails);
            initInputState();
        }
    }
        
    protected void closing() {
        boolean saved = false;
        try{
            orderMst.setStatusId(Constants.STATUS_TRANS_CLOSED);
            saved = ServicesList.getOrderService().save(orderMst);
            orderMst.setUpdatedLog(ServicesList.getSystemUserService().getUserIdLog());
        } catch(Exception ex){
            log.error(ex);
            JOptionPane.showMessageDialog(this, "Data gagal Closing.", "Error",JOptionPane.ERROR_MESSAGE);
        }
        if (saved) { initInputState(); }
    }
    
    @Override
    protected void initButtonState(boolean state) {
         btnSave.setEnabled(state);
         //ngahaja
         if (state) { btnPosting.setEnabled(false); }
    }
    
    protected void initInputState() {
        long transId = orderMst.getId()==null ? 0:orderMst.getId();
        Integer statusId = orderMst.getStatusId()==null ? 0:orderMst.getStatusId();
        long revisiId = orderMst.getRevisedId()==null ? 0:orderMst.getRevisedId();
  
        txtAddTOP.setEnabled(statusId==0);
        txtNotes.setEnabled(statusId==0);
        txtSupplier.setEnabled(statusId==0);
        txtRevisi.setEnabled(statusId==0);
        chkTahan.setEnabled(statusId==0);
        dtpOrder.setEnabled(statusId==0);
       
        btnPrint.setEnabled(transId>0);
        btnSave.setEnabled(transId==0 && statusId==Constants.STATUS_TRANS_OPEN);
        btnPosting.setEnabled(transId>0 && statusId==Constants.STATUS_TRANS_OPEN);
        btnClose.setEnabled(transId>0 && statusId<Constants.STATUS_TRANS_CLOSED);
        btnRevisi.setEnabled(transId>0 && statusId==Constants.STATUS_TRANS_POSTED);
        btnDelete.setEnabled(statusId==Constants.STATUS_TRANS_OPEN);
    }

    protected void showOrderList(long id) {
        cmbOrders.removeItemListener(itemListener);
        List<NameValueList> orderList = ServicesList.getOrderService().getListByEntryId(id); 
        cmbOrders.setModel(ComponentUtils.getDefaultComboBoxModel(orderList));
        cmbOrders.addItemListener(itemListener);
    }
    
    private void createAutoOrder() {
        int jadwal = new LookupScheduleFrm().execute(); 
        if (jadwal>0) {
            int row = 0;
            List<Item> items = ServicesList.getItemService().getAutOrder(jadwal);
            if (!items.isEmpty()) {
                orderMst.getOrderDetails().clear();
            }
            
            for (Item item:items) {
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setItem(item);
                                        
                //cari juga hpp
                ItemHpp hpp = ServicesList.getItemHppService().get(item.getId(), dtpOrder.getDate()); 
                orderDetail.setItemHpp(hpp);
                orderDetail.setTop(hpp.getTop());
                orderDetail.setUnit(hpp.getUnit());
                
                int qtyOrder = 0;
                BigDecimal stok = new BigDecimal("0");
                ItemStok itemStok = ServicesList.getItemStokService().get(item.getId(), Constants.GUDANG_INDUK); 
                if (itemStok!=null) { stok = itemStok.getStok(); }
                if (item.getStokMax()==null) { item.setStokMax(0); }
                if (item.getStokMin()==null) { item.setStokMin(0); }
                if (item.getStokX()==null) { item.setStokX(0); }
                    
                int cond1 = stok.compareTo(new BigDecimal(item.getStokMin()));
                int cond2 = stok.compareTo(new BigDecimal(0));
                
                if ((stok.compareTo(new BigDecimal(item.getStokMin())) <= 0) && 
                        (stok.compareTo(new BigDecimal(0)) >= 0)) {
                    qtyOrder = (item.getStokMax() - stok.intValue()) / hpp.getFraksi();
                }
                
                orderDetail.setQtyCrt(new BigDecimal(qtyOrder));        
                orderMst.getOrderDetails().add(orderDetail);
                orderTM.fireTableRowsInserted(row, row);
                calculateDiskon(row);
                calculate(row);
                orderTM.fireTableRowsUpdated(row, row);
                row++;
            }
        }
    }
    
    private void printOrder() {
       // JasperPrint jp = ServicesList.getOrderService().printData(0,orderMst.getId());
        JasperPrint jp = ServicesList.getOrderService().printData(orderMst.getAutoId(), 0);
        JasperViewer.viewReport(jp);
    }
    
    private void printOrders() {
        JasperPrint jp = ServicesList.getOrderService().printData(orderMst.getAutoId(), 0);
        JasperViewer.viewReport(jp);
    }
    
    @Override
    protected void initComponentsRules() {
        btnNew.registerKeyboardAction(btnNew.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);
 
        btnNew.registerKeyboardAction(btnNew.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
        
        btnPosting.registerKeyboardAction(btnPosting.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);

        btnPosting.registerKeyboardAction(btnPosting.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);

        btnSave.registerKeyboardAction(btnSave.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);
 
        btnSave.registerKeyboardAction(btnSave.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
        
        btnPrint.registerKeyboardAction(btnPrint.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, false)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, false), JComponent.WHEN_FOCUSED);
 
        btnPrint.registerKeyboardAction(btnPrint.getActionForKeyStroke(
            KeyStroke.getKeyStroke(KeyEvent .VK_SPACE, 0, true)), KeyStroke.getKeyStroke(KeyEvent .VK_ENTER, 0, true), JComponent.WHEN_FOCUSED);
        
        TextComponentUtils.setNumericTextOnly(txtAddTOP);
        
        itemCEditor.setName("itemCEditor");
        ctnCEditor.setName("ctnCEditor");
        pcsCEditor.setName("pcsCEditor");
        txtAddTOP.addKeyListener(new ActionKeyListener());
        txtNotes.addKeyListener(new ActionKeyListener());
        txtRevisi.addKeyListener(new ActionKeyListener());
        txtSupplier.addKeyListener(new ActionKeyListener());
        chkTahan.addKeyListener(new ActionKeyListener());
        itemCEditor.addKeyListener(new ActionKeyListener());
            
        txtAddTOP.addFocusListener(new ActionFocusGained());
        txtNotes.addFocusListener(new ActionFocusGained());
        txtRevisi.addFocusListener(new ActionFocusGained());
        txtSupplier.addFocusListener(new ActionFocusGained());
        chkTahan.addFocusListener(new ActionFocusGained());
        itemCEditor.addFocusListener(new ActionFocusGained());

        dtpOrder.getDateEditor().addPropertyChangeListener(
            new PropertyChangeListener() {
            @Override public void propertyChange(PropertyChangeEvent evt) {
                if ("date".equals(evt.getPropertyName())) {
                    if(!evt.getNewValue().equals(evt.getOldValue())) {
                    }
                }
            }
        });
   
        TableUtil.setTableActionKeyMap(grid);
        grid.addKeyListener( new GridKeyListener());
    }
    
    private void setTableLookStyle() {
        
    }
}
